package com.bjpowernode.services;
import com.bjpowernode.beans.Stu;
import com.bjpowernode.dao.StuDao;
import com.bjpowernode.dao.StuDaoImp;
import com.bjpowernode.exception.MyRangeException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Random;
public class StuServicesImp implements StuServices {



    //学号缓存[1000-5000]功能==========================================
    //学号缓存只需要个自己使用，因此是private
    //学号缓存需要初始化，并且也只有一个份缓存，因此是static
    //初始化使用静态块
    //每次拿出学号区号取出集合的最顶端的元素，每次还回学号也需要还回到结合的最顶端，因此选用LinkedList集合
    //LinkedList.removeFirst方法支持删除最顶端，并返回顶端元素
    //LinkedList.addFirst方法添加元素到最顶端
    private static LinkedList<Integer> ids = new LinkedList<>();
    //学号缓存初始化
    static {
        //初始化学号缓存
        for (int i = 1005; i <= 5000; i++) {
            ids.add(i);
        }
    }
    //学号缓存[1000-5000]功能End==========================================

    //业务需要关联dao
    StuDao stuDao = new StuDaoImp();
    @Override
    public ArrayList<Stu> getAll() {
        return stuDao.getAll();
    }

    @Override
    public boolean add(Stu stu) throws MyRangeException {
        //学生的属性验证
        stu.validation();
        //需要补充一个ID
        Integer id = ids.removeFirst();
        //学生的学号是程序获取，而不是用户输入，因此需要业务补充学号
        stu.setId(id);
        return stuDao.add(stu);
    }

    @Override
    public boolean del(Stu stu) {
        //学号还回去
        ids.addFirst(stu.getId());
        return stuDao.del(stu);
    }

    @Override
    public boolean edit(Stu stu) {
        //不做处理，也不做验证，还是因为Tableview选择行就是DB集合里面的stu本身的原因
        return stuDao.edit(stu);
    }

    @Override
    public ArrayList<Stu> call(int num) throws MyRangeException {
        //准备返回的集合
        ArrayList<Stu> result = new ArrayList<>();
        //随机抽到的学生全集集合的下标
        HashSet<Integer> indexs = new HashSet<>();
        //学生全集集合
        ArrayList<Stu> all = stuDao.getAll();
        //验证边界：没有学生情况
        if (all.size() == 0) {
            //需要触发异常
            throw new MyRangeException("没有任何学生，无法点名");
        }
        //验证点名范围：【业务验证数据范围，控制器验证数据类型】
        if (num < 1 || num > all.size()) {
            //需要触发异常
            throw new MyRangeException("点名人数数量输入错误");
        }
        //随机抽的下标的数量
        Random random = new Random();
        while (true) {
            //随机抽一个下标
            int temp = random.nextInt(all.size());
            //添加到Set集合，目的是为了去重
            indexs.add(temp);
            //随机抽几个停止
            if (indexs.size() == num) {
                break;
            }
        }
        //遍历下标Set集合
        for (Integer index : indexs) {
            result.add(all.get(index));
        }
        return result;
    }
}
